package CassroomPractice.SingiyLinkedlist;

import java.util.NoSuchElementException;
import java.util.Objects;

public class SinglyList<E> implements ListOperation<E> {

    private final SinglyNode<E> head = new SinglyNode<>(null, null);

    private int size;

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public void addFirst(E item) {
        head.next = new SinglyNode<>(item, head.next);
        size++;
    }

    @Override
    public void addLast(E item) {
        SinglyNode<E> addLastNode = head;
        while (addLastNode.next != null){
            addLastNode = addLastNode.next;
        }
        addLastNode.next = new SinglyNode<>(item, null);
        size++;
    }

    @Override
    public void add(int index, E item) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("index不合法：" + index);
        }
        SinglyNode<E> inNode = head;
        for (int i = 0; i < index; i++) {
            inNode = inNode.next;
        }
        inNode.next = new SinglyNode<>(item,inNode.next);
        size++;
    }

    @Override
    public E getFirst() {
        if (isEmpty()){
            throw new NoSuchElementException("空链表");
        }
        return head.next.value;
    }

    @Override
    public E getLast() {
        if (isEmpty()){
            throw new NoSuchElementException("空链表");
        }
        SinglyNode<E> getLastNode = head;
        while (getLastNode.next != null) {
            getLastNode = getLastNode.next;
        }
        return getLastNode.value;
    }

    @Override
    public E get(int index) {
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("index不合法：" + index);
        }
        SinglyNode<E> getNode = head.next;
        for (int i = 0; i < index; i++) {
            getNode = getNode.next;
        }
        return getNode.value;
    }

    @Override
    public E set(int index, E item) {
        if (isEmpty()){
            throw new NoSuchElementException("空链表");
        }
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("index不合法：" + index);
        }
        SinglyNode<E> setNode = head.next;
        for (int i = 0; i < index; i++) {
            setNode = setNode.next;
        }
        E old = setNode.value;
        setNode.value = item;
        return old;
    }

    @Override
    public E removeFirst() {
        if (isEmpty()) {
            throw new NoSuchElementException("空链表");
        }
        E value = head.next.value;
        head.next = head.next.next;
        size--;
        return value;
    }

    @Override
    public E removeLast() {
        if (isEmpty()) {
            throw new NoSuchElementException("空链表");
        }
        SinglyNode<E> removeLastNode = head;
        while (removeLastNode.next.next != null) {
            removeLastNode = removeLastNode.next;
        }

        E value = removeLastNode.next.value;
        removeLastNode.next = null;
        return value;
    }

    @Override
    public E remove(int index) {
        if (isEmpty()){
            throw new NoSuchElementException("空链表");
        }
        if (index < 0 || index >= size) {
            throw new IndexOutOfBoundsException("index不合法：" + index);
        }
        SinglyNode<E> removeNode = head;
        for (int i = 0; i < index; i++) {
            removeNode = removeNode.next;
        }
        E value = removeNode.next.value;
        removeNode.next = removeNode.next.next;
        size--;
        return value;
    }

    @Override
    public boolean remove(Object obj) {
        if (isEmpty()) {
            throw new NoSuchElementException("空链表");
        }
        SinglyNode<E> removeNode = head;
        while (removeNode.next != null) {
            if (Objects.equals(removeNode.next.value, obj)) {
                removeNode.next = removeNode.next.next;
                size--;
                return true;
            }else {
                removeNode = removeNode.next;
            }
        }
        return false;
    }
}
